﻿using Microsoft.Owin.Security.Infrastructure;
using System;
using System.Linq;
using System.Threading.Tasks;
using Common.JWT;
using System.Configuration;

namespace OAuthServerApi
{
    public class CustomAuthorizeCodeProvider : AuthenticationTokenProvider
    {
        public CustomAuthorizeCodeProvider() { }

        public override async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
            try
            {
                using (var db = new DbOAuthHelper())
                {
                    #region 生成code-1
                    //var claims = context.Ticket.Identity.Claims;
                    //if (claims.Where(x => x.Type == CustomClaimsType.RequestUniqueId).Count() == 0)
                    //{
                    //    context.Ticket.Identity.AddClaim(new Claim(CustomClaimsType.RequestUniqueId, Guid.NewGuid().ToString("n")));
                    //}
                    //var customClaims = claims.Where(x => x.Type.StartsWith("as:")).Select(x => new
                    //{
                    //    x.Type,
                    //    x.Value
                    //});
                    ////claim信息
                    //var client = customClaims.FirstOrDefault(x => x.Type == CustomClaimsType.ClientId);
                    //var user = customClaims.FirstOrDefault(x => x.Type == CustomClaimsType.UserId);
                    //var response = customClaims.FirstOrDefault(x => x.Type == CustomClaimsType.ResponseType);
                    ////生成code
                    //var unsignData = string.Join(".", customClaims);
                    //var tokenArr = JwtHelper.GetHashAlgorithms()[JwtHashAlgorithm.HS256](Encoding.UTF8.GetBytes(signKey), Encoding.UTF8.GetBytes(unsignData));
                    //var token = string.Empty;
                    //foreach (var s in tokenArr)
                    //{
                    //    token += s.ToString("x2");
                    //} 
                    #endregion
                    var claims = context.Ticket.Identity.Claims;
                    //claim信息
                    var client = claims.FirstOrDefault(x => x.Type == CustomClaimsType.ClientId);
                    var user = claims.FirstOrDefault(x => x.Type == CustomClaimsType.UserId);
                    var response = claims.FirstOrDefault(x => x.Type == CustomClaimsType.ResponseType);
                    var ticket = context.SerializeTicket();
                    var token = JwtHelper.MD5(string.Concat(ticket, Guid.NewGuid().ToString("n")), 32);
                    //生成票据
                    var tokenModel = new OAuthCode
                    {
                        GrantCode = token,
                        ClientHash = client == null ? string.Empty : client.Value,
                        UserHash = user == null ? string.Empty : user.Value,
                        ExperiesDate = context.Ticket.Properties.ExpiresUtc.HasValue ? context.Ticket.Properties.ExpiresUtc.Value.LocalDateTime : DateTime.Now.AddSeconds(AppConstNum.refresh_expires_second),
                        ResponseType = response == null ? 0 : int.Parse(response.Value),
                        Ticket = ticket
                    };
                    var result = await db.AddCode(tokenModel);
                    if (result > 0)
                    {
                        context.SetToken(token);
                        await base.CreateAsync(context);
                    }
                    else
                    {
                        await Task.FromResult<object>(null);
                        return;
                    }
                }
            }
            catch
            {
                throw new AggregateException("生成code失败");
            }
        }

        public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            if (string.IsNullOrEmpty(context.Token))
            {
                await Task.FromResult<object>(null);
                return;
            }
            try
            {
                using (var db = new DbOAuthHelper())
                {
                    var code = await db.GetOAuthCode(context.Token);
                    if (code == null)
                    {
                        await Task.FromResult<object>(null);
                        return;
                    }
                    var elapsedTicks = (DateTime.Now.Ticks - code.ExperiesDate.Ticks);
                    var elapsedSpan = new TimeSpan(elapsedTicks);
                    //验证code失效时间
                    if (elapsedSpan.TotalSeconds >= 0)
                    {
                        await Task.FromResult<object>(null);
                        return;
                    }
                    context.DeserializeTicket(code.Ticket);
                    if (context.Ticket != null)
                    {
                        context.OwinContext.Set(OwinEnvType.GrantCode, code);
                    }
                }
            }
            catch
            {
                throw new AggregateException("验证Code失败");
            }
        }
    }

}